package com.googlecode.jlogindexer.utils;

import java.io.IOException;
import java.net.MalformedURLException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer;

import com.googlecode.jlogindexer.document.LogDocument;

public class CopyOfSolrUtils {
	
	private String solrUrl;
	private CommonsHttpSolrServer solrServer=null;
	private boolean isSolrServerUp=false;
	private int docCount=0;
	private String PING_URL=null;
	
	private static long SERVER_POLL_DELAY=5;
	private static int PING_TIMEOUT=500;
	private HttpClient httpClient=null;
	
	//private Timer timerService=null;
	private ScheduledExecutorService timerService=null;
	
	
	private CopyOfSolrUtils() {
		//TODO Initiate local server otherwise
	}
	
	public CopyOfSolrUtils(String solrUrl){
		this.solrUrl=solrUrl;
	}
	

	public void initServer() {
		try {
			System.err.println("First Contact with Server....");
			PING_URL=solrUrl+"/admin/ping";
			initHttpClient();
			solrServer =new CommonsHttpSolrServer(solrUrl);
			//timerService=new Timer();
			timerService=Executors.newScheduledThreadPool(3); //3 is my lucky number;
			//resolveServerAvailability();
			startTickingTimer();
		} catch (MalformedURLException e) {
			System.err.println("Unable to resolve Solr Url"+e.getMessage());
		}
			
	}

	public boolean isServerAvailable() {
	
		return isSolrServerUp;
	}
	
	/**
	 * Resolves whether the Solr server is up and running. Sets the isSolrServerUp field accordingly. 
	 * TODO Could bring up the local server if false.
	 */
	private void resolveServerAvailability() {
			
			if (solrServer!=null){
				System.out.println("Pinging serverrrr now....");
				//SolrPingResponse solrResponse = solrServer.ping();
				
				
				//int status = httpClient.solrResponse.getStatus();
				int status=pingSolrServer();
				System.out.println("Ping done.......  ");
				System.err.println("Server STATUS IS "+status);
					if (status==200){
						System.err.println("Server status is active....");
						isSolrServerUp=true;
					}
					else{
						System.err.println("Server status is shutdown.... ");
						isSolrServerUp=false;
					}
			}
			else{
				isSolrServerUp=false;
			}
		
			
			/*if (solrServer!=null){
				System.out.println("Pinging serverrrr now....");
//				SolrPingResponse solrResponse = solrServer.ping();
//				
//				System.out.println("Ping threw an exception....");
//				int status = solrResponse.getStatus();
				
				int status=pingSolrServer();
				//System.out.println("Server STATUS IS "+status);
					if (status==0){
						System.err.println("Server status is active....");
						isSolrServerUp=true;
					}
					else{
						System.err.println("Server status is shutdown.... ");
						isSolrServerUp=false;
					}
			}
			else{
				isSolrServerUp=false;
			}
			*/
		
				
	}

	private void startTickingTimer() {
		System.err.println("TICKING TIMER START");
		timerService.scheduleAtFixedRate(new SolrPoller(), -1,SERVER_POLL_DELAY,TimeUnit.SECONDS);//start now
		
	}
	
	
	private class SolrPoller implements Runnable{
		
		public void run() {
			System.err.println("Server being Pollled right now........");
			System.gc();
			System.out.println("Is server Available....."+isServerAvailable());
			if (!(isServerAvailable())){
				resolveServerAvailability();
			}
		}
		
	};


	public void shutDownServer() {
		// TODO Need to identify what exactly shutting down client means in Solr world. As of now, I am just nullifying the solrserver. 
		//WHAT THE HELL happened to the http connection?
		System.err.println("Shutting down server???");
		try {
			solrServer.commit(); //Commit the unflushed records
		} catch (SolrServerException e) {
			System.err.println("Problem closing Solr server client connection"+e.getMessage());
		} catch (IOException e) {
			System.err.println("Problem closing Solr server client connection"+e.getMessage());
		}
		
	}

	public void addDocumentToSolr(LogDocument logDocument) {
		try {
			System.out.println("About to add to Solr");
			solrServer.addBean(logDocument);
			docCount++;
			System.out.println("Successfully ADDED document....Document Count.....");
			solrServer.commit();
			System.out.println("Document committed.....");
			if (docCount%10==0){
				solrServer.commit();
				System.gc();
			}
		} catch (SolrServerException e) {
			System.err.println("Could not add document to Solr Server. Possibly Down?"+e.getMessage());
		} 
		catch (IOException e) {
			System.err.println("Could not add document to Solr Server. Possibly Down?"+e.getMessage());
		}
	}
	
	/*private int pingSolrServer(){
		
		DefaultHttpClient httpclient = new DefaultHttpClient();
		int status=1;
		try {
			HttpContext localContext = new BasicHttpContext();
			HttpGet httpget = new HttpGet(solrUrl); 
			HttpResponse response = httpclient.execute(httpget, localContext);
			HttpHost target = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
			HttpUriRequest req = (HttpUriRequest) localContext.getAttribute(ExecutionContext.HTTP_REQUEST);
			
			StatusLine statusLine = response.getStatusLine();
			System.err.println("STATUS CODE OF PING IS >>>>>>>>>"+statusLine.getStatusCode());
			status=statusLine.getStatusCode();
			
		} catch (ClientProtocolException e) {
			System.err.println("Client Protocol exception"+e.getMessage());
			status=1;
			//e.printStackTrace();
			
		} catch (IOException e) {
			System.err.println("IO Exception ...."+e.getMessage());
			status=1;
			//e.printStackTrace();
		}
		
		return status;

	}
	*/
	private int pingSolrServer(){
		int status=0;
		GetMethod method =null;
	    try {
	    	System.out.println("Getting httpClient");
	    	System.out.println("httpClient initiatied "+httpClient);
			method = new GetMethod(PING_URL);
			System.out.println("About to execute method");
			status = httpClient.executeMethod(method);
			System.err.println("Ping status is...... "+status);
		} catch (HttpException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally{
			method.releaseConnection();
		}
		
		return status;
	}
	
	private HttpClient initHttpClient() {
		HttpClientParams params=new HttpClientParams();
		params.setConnectionManagerTimeout(PING_TIMEOUT);
		params.setSoTimeout(PING_TIMEOUT);
		httpClient.setParams(params);
		return httpClient;
	}

	
}